﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using GP.Scripts.Battle;
using Gp.Scripts.Data;
using UnityEngine;

namespace Gp.Scripts.Core
{
    public class BuffChangeEvent
    {
        public BuffChangeEvent(bool isBuffAdd, BaseBuff buff)
        {
            IsBuffAdd = isBuffAdd;
            Buff      = buff;
        }

        public bool IsBuffAdd { get; }

        public BaseBuff Buff { get; }
    }


    public class UnitBuffCom : IUnitComponent
    {
        private Dictionary<string, BaseBuff> _buffs = new();

        public BaseUnit Unit { get; private set; }

        private readonly List<BaseBuff> _removing = new();

        public IEnumerable<BaseBuff> Buffs => _buffs.Values;


        public void Init(BaseUnit unit)
        {
            Unit = unit;


            // // 添加受伤buff
            // AddBuff(new InjuryBuff());
        }

        public IEnumerable<BonusInfo> Bonus()
        {
            return _buffs.Values.Select(buff => new BonusInfo(buff.Bonus(), buff)).ToList();
        }


        public void OnUpdate()
        {
            if (_removing.Count == 0) return;

            _deleting = true;
            // 统一删除Buff
            foreach (var r in _removing)
            {
                if (!_buffs.Remove(r.BuffId)) continue;

                // 发送删除事件
                try
                {
                    r.Remove();
                    // OnBuffChange?.Invoke(this, new BuffChangeEvent(false, r));
                }
                catch (Exception e)
                {
                    Debug.LogError(e.Message);
                }
            }

            _removing.Clear();
            _deleting = false;
        }

        /// <returns>是否成功添加buff（未发生叠加则返回true）</returns>
        public bool AddBuff(BaseBuff buff)
        {
            // 如果存在同类 buff， 则仅进行叠加处理
            if (_buffs.TryGetValue(buff.BuffId, out var old))
            {
                old.OnBuffAdditive(buff);
                return false;
            }
            // 发送新增buff事件

            _buffs[buff.BuffId] = buff;
            buff.Apply(this);
            // OnBuffChange?.Invoke(this, new BuffChangeEvent(true, buff));

            return true;
        }


        private bool _deleting;

        /// <summary>
        /// 回合开始更新
        /// </summary>
        public IEnumerator OnTurnStart()
        {
            yield return WaitDeleting();
            foreach (var baseBuff in _buffs.Values.ToArray())
            {
                yield return baseBuff.TurnStartUpdate();
            }
        }

        public IEnumerator OnTurnEnd()
        {
            yield return WaitDeleting();
            foreach (var baseBuff in _buffs.Values.ToArray())
            {
                yield return baseBuff.TurnEndUpdate();
            }
        }


        private IEnumerator WaitDeleting()
        {
            while (_deleting) yield return 0;
        }


        public bool HasBuff<T>() where T : BaseBuff
        {
            return HasBuff(BaseBuff.GetBuffId<T>());
        }

        public bool HasBuff(string buffId)
        {
            return _buffs.ContainsKey(buffId);
        }


        public T GetBuff<T>() where T : BaseBuff
        {
            return _buffs.GetValueOrDefault(BaseBuff.GetBuffId<T>()) as T;
        }


        public void RemoveBuff(BaseBuff buff)
        {
            if (buff == null) return;
            _removing.Add(buff);
        }


        public bool RemoveBuff<T>() where T : BaseBuff
        {
            if (!_buffs.TryGetValue(BaseBuff.GetBuffId<T>(), out var buff))
            {
                return false;
            }

            RemoveBuff(buff);
            return true;
        }

        public void OnDestroy()
        {
            // this._buffs.Clear();
            // this._buffs = null;
        }
    }
}